// 包心菜
import 'dart:math';

import 'package:flame/components.dart';
import 'package:flame/game.dart' show NotifyingVector2;
import 'package:flutter_flame/config/AssetsName.dart';
import 'package:flutter_flame/worlds/game/components/bullet/Bullet.dart';
import 'package:flutter_flame/worlds/game/model/PlantModel.dart';

import '../NormalZombie.dart';

class Cabbage extends Bullet {
  final double gravity = 800; // 重力加速度
  final NormalZombie targetZombie;

  double elapsedTime = 0; // 飞行时间
  late double initialX; // 包心菜开始的横向x
  late double initialY; // 包心菜开始的纵向y
  late double vX; // 包心菜横向速度
  late double vY = -600; // 包心菜垂直速度
  NotifyingVector2 get targetPosition => NotifyingVector2(
        targetZombie.position.x - 35,
        targetZombie.position.y,
      );

  Cabbage({
    required Vector2 position,
    required this.targetZombie,
  }) : super(
          AssetsName.spriteCabbagePultCabbage,
          position: position,
          plantModel: PlantModel.cabbagepult,
        ) {
    size = Vector2(25, 25);
  }

  @override
  Future<void> onLoad() async {
    await super.onLoad();
    addHitBox();
    priority = bulletPriority;
    initialX = position.x;
    initialY = position.y;
    // 竖直方向位移
    double dy = targetPosition.y - initialY;
    // 解一元二次方程: 0.5*g*t^2 + vY*t - dy = 0
    double a = 0.5 * gravity;
    double b = vY;
    double c = -dy;
    double discriminant = b * b - 4 * a * c;

    if (discriminant < 0) {
      // 解不存在，默认丢弃
      removeFromParent();
      return;
    }

    // 取正根作为飞行时间
    double t1 = (-b + sqrt(discriminant)) / (2 * a);
    double t2 = (-b - sqrt(discriminant)) / (2 * a);
    double flightTime = t1 > 0 ? t1 : t2;
    vX = (targetPosition.x - initialX) / flightTime; // 水平方向速度
    if (vX < 0) vX = 30;
    anchor = Anchor.center;
  }

  @override
  void update(double dt) {
    elapsedTime += dt; // 当前时间
    position.x = initialX + vX * elapsedTime;
    position.y =
        initialY + vY * elapsedTime + 0.5 * gravity * elapsedTime * elapsedTime;
    angle += dt * 5; // 旋转
    if (position.x > game.size.x) {
      removeFromParent();
    }
  }
}
